package com.cmc.cloud.cmclink.doc.mq;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cmc.cloud.cmclink.doc.api.document.emums.BusinessTypeEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.CntrStatusEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.ExImTypeEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.SiStatusEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.SoStatusEnum;
import com.cmc.cloud.cmclink.doc.api.document.req.si.BlnoDetailReqDto;
import com.cmc.cloud.cmclink.doc.convert.*;
import com.cmc.cloud.cmclink.doc.entity.BlnoDO;
import com.cmc.cloud.cmclink.doc.entity.BlnoVslvoyDO;
import com.cmc.cloud.cmclink.doc.entity.VoyageLockDO;
import com.cmc.cloud.cmclink.doc.mapper.BlnoMapper;
import com.cmc.cloud.cmclink.doc.service.BlnoCntrService;
import com.cmc.cloud.cmclink.doc.service.si.*;
import com.cmc.cloud.cmclink.doc.service.so.OperateLogService;
import com.cmc.cloud.cmclink.doc.util.VslvoyUtil;
import com.cmc.cloud.cmclink.doc.vo.blnocargovo.BlnoCargoUpdateReqVO;
import com.cmc.cloud.cmclink.doc.vo.blnocntrvo.BlnoCntrUpdateReqVO;
import com.cmc.cloud.cmclink.doc.vo.blnopaymentvo.BlnoPaymentUpdateReqVO;
import com.cmc.cloud.cmclink.doc.vo.blnoscnvo.BlnoScnUpdateReqVO;
import com.cmc.cloud.cmclink.doc.vo.blnovo.BlnoBaseInfoVO;
import com.cmc.cloud.cmclink.doc.vo.blnovo.BlnoInfoVO;
import com.cmc.cloud.cmclink.doc.vo.blnovslvoyvo.BlnoVslvoyUpdateReqVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.operatelog.OperateLogCreateReqVO;
import com.cmes.framework.security.core.LoginUser;
import com.cmes.framework.security.core.util.SecurityFrameworkUtils;
import com.cmes.framework.tenant.core.context.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import static com.cmc.cloud.cmclink.doc.api.document.emums.SiOperateTypeEnum.SUBMIT_SI;

/**
 * 消费者
 *
 * @author huzheng
 * @date 2025/09/16 13:36
 **/
@Slf4j
@Component
@RocketMQMessageListener(consumerGroup = "rocketmq_si_create_consumer_group",
        topic = "topic-edi-si-import", maxReconsumeTimes = 3)
public class SiEdiConsumer implements RocketMQListener<SiEdiReqVO> {

    private static final String FUNCODE_SI_CREATE = "9";
    private static final String FUNCODE_SI_UPDATE = "5";
    private static final String FUNCODE_SI_DELETE = "3";
    private static final String SI_EDI_CREATOR = "9876543212345";
    private static final String SI_EDI_REQUEST_SUCCESS = "200";
    private static final String SI_EDI_REQUEST_FAIL = "500";

    private final static String SI_OPERATE_TYPE = "SI_Operate";

    @Resource
    private BlnoService blnoService;
    @Resource
    private BlnoMapper blnoMapper;
    @Resource
    private BlnoPaymentService blnoPaymentService;
    @Resource
    private BlnoScnService blnoScnService;
    @Resource
    private BlnoCargoService blnoCargoService;
    @Resource
    private BlnoCntrService blnoCntrService;
    @Resource
    private BlnoVslvoyService blnoVslvoyService;
    @Autowired
    private MyProducer myProducer;
    @Autowired
    private OperateLogService operateLogService;
    @Autowired
    private VoyageLockService voyageLockService;

    @Override
    public void onMessage(SiEdiReqVO message) {
        log.info("topic-edi-si-import-getMessage:{}", JSON.toJSONString(message));
        LoginUser originLoginUser = new LoginUser();
        originLoginUser.setId(Long.parseLong(SI_EDI_CREATOR));
        TenantContextHolder.setTenantId(172L);
        SecurityFrameworkUtils.setNoneHttpLoginUser(originLoginUser);
        String blNo = message.getData().getBlNo();
        if (StringUtils.isEmpty(blNo)) {
            return;
        }
        String funCode = message.getFuncCode();
        List<String> msgList = new ArrayList<>();
        HashMap<String, Object> messageResp = new HashMap<>(8);
        messageResp.put("code", SI_EDI_REQUEST_SUCCESS);
        messageResp.put("msgId", message.getMsgId());
        BlnoBaseInfoVO blnoBaseVo = BlnoConvert.INSTANCE.convertBlnoBaseInfoVO(message.getData());
        //航线信息     如果锁船 不可进行任何操作  但是如果是空箱不需要判断
        List<BlnoVslvoyUpdateReqVO> blnoVslvoys = BlnoVslvoyConvert.INSTANCE.ediConvertBlnoVslvoyUpdateReqVO(message.getData().getVslvoyList());
        if(!CntrStatusEnum.E.getValue().equals(blnoBaseVo.getCntrStatus())){
            boolean isLocked = checkLockVoyage(BeanUtil.copyToList(blnoVslvoys, BlnoVslvoyDO.class));
            if(isLocked){
                msgList.add("已锁船不可操作");
                messageResp.put("msgList", msgList);
                messageResp.put("code", SI_EDI_REQUEST_FAIL);
                myProducer.sendMessage("edi-import-response", messageResp);
                return;
            }
        }
        List<String> ediBiz = Arrays.asList(FUNCODE_SI_CREATE, FUNCODE_SI_UPDATE, FUNCODE_SI_DELETE);
        if (!ediBiz.contains(funCode)) {
            msgList.add("不在业务受理范围的funcCode:" + funCode);
            messageResp.put("msgList", msgList);
            messageResp.put("code", SI_EDI_REQUEST_FAIL);
            myProducer.sendMessage("edi-import-response", messageResp);
            return;
        }
        if (FUNCODE_SI_DELETE.equals(funCode)) {
            try {
                BlnoDetailReqDto reqDto = new BlnoDetailReqDto();
                reqDto.setBlNo(blNo);
                BlnoDO blnoDO = blnoService.getBlno(reqDto);
                if (null != blnoDO) {
                    blnoMapper.deleteById(blnoDO.getId());
                    deleteBlnoRelations(blnoDO.getId());
                    msgList.add("提单信息删除成功，提单号：" + blNo + "，siId:" + blnoDO.getId());
                }
            } catch (Exception e) {
                msgList.add(e.getMessage());
                messageResp.put("code", SI_EDI_REQUEST_FAIL);
            }
            messageResp.put("msgList", msgList);
            myProducer.sendMessage("edi-import-response", messageResp);
            return;
        }
        BlnoInfoVO blnoInfoVO = new BlnoInfoVO();
        //基础信息
        blnoBaseVo.setDatasource(message.getData().getDataSource());
        blnoInfoVO.setBlnoBasInfoVO(blnoBaseVo);
        //航线信息
        blnoInfoVO.setBlnoVslvoys(blnoVslvoys);
        //支付信息
        List<BlnoPaymentUpdateReqVO> blnoPayments = BlnoPaymentConvert.INSTANCE.ediConvertBlnoPaymentUpdateReqVo(message.getData().getPaymentList());
        blnoInfoVO.setBlnoPayments(blnoPayments);
        //常用收发通
        List<BlnoScnUpdateReqVO> blnoScnUpdateReqVos = BlnoScnConvert.INSTANCE.ediConvertBlnoScnUpdateReqVO(message.getData().getScnList());
        blnoInfoVO.setBlnoScns(blnoScnUpdateReqVos);
        //箱信息
        List<BlnoCntrUpdateReqVO> blnoCntrs = BlnoCntrConvert.INSTANCE.ediConvertBlnoCntrUpdateReqVO(message.getData().getCntrList());
        blnoInfoVO.setBlnoCntrs(blnoCntrs);
        //货物信息
        List<BlnoCargoUpdateReqVO> blnoCargos = BlnoCargoConvert.INSTANCE.ediConvertBlnoCargoUpdateReqVO(message.getData().getCargoList());
        blnoInfoVO.setBlnoCargos(blnoCargos);
        try {
            if (FUNCODE_SI_CREATE.equals(funCode)) {
                BlnoDetailReqDto reqDto = new BlnoDetailReqDto();
                reqDto.setBlNo(blNo);
                BlnoDO blnoDO = blnoService.getBlno(reqDto);
                if (null != blnoDO) {
                    msgList.add("要创建的提单信息已存在，如需更新请走更新流程，提单号：" + blNo + "，siId:" + blnoDO.getId());
                    messageResp.put("msgList", msgList);
                    messageResp.put("code", SI_EDI_REQUEST_FAIL);
                    myProducer.sendMessage("edi-import-response", messageResp);
                    return;
                }
                Long bnNoId = commitEdiData(blnoInfoVO, SI_EDI_CREATOR);
                msgList.add("提单信息创建成功，提单号：" + blNo + "，siId:" + bnNoId);
                if (!message.getNeedApproval()) {
                    blnoDO = blnoMapper.selectById(bnNoId);
                    blnoDO.setSiStatus(SiStatusEnum.BookingConfirmed.getValue());
                    blnoMapper.updateById(blnoDO);
                }
            }
            if (FUNCODE_SI_UPDATE.equals(funCode)) {
                BlnoDetailReqDto reqDto = new BlnoDetailReqDto();
                reqDto.setBlNo(blNo);
                BlnoDO blnoDO = blnoService.getBlno(reqDto);
                if (null != blnoDO) {
                    deleteBlnoRelations(blnoDO.getId());
                    commitEdiData(blnoInfoVO, SI_EDI_CREATOR);
                    if (!message.getNeedApproval()) {
                        blnoDO.setSiStatus(SiStatusEnum.BookingConfirmed.getValue());
                        blnoMapper.updateById(blnoDO);
                    }
                    msgList.add("提单信息更新成功，提单号：" + blNo + "，siId:" + blnoDO.getId());
                } else {
                    msgList.add("提单信息不存在，提单号：" + blNo);
                }
            }
        } catch (Exception e) {
            msgList.add(e.getMessage());
            messageResp.put("code", SI_EDI_REQUEST_FAIL);
        }
        messageResp.put("msgList", msgList);
        myProducer.sendMessage("edi-import-response", messageResp);
    }

    public void deleteBlnoRelations(Long blnoId) {
        blnoPaymentService.deleteBlnoPaymentByblnoId(blnoId);
        blnoVslvoyService.deleteBlnoVslvoyByblnoId(blnoId);
        blnoScnService.deleteBlnoScnByblnoId(blnoId);
        blnoCargoService.deleteBlnoCargoByBlnoId(blnoId);
        blnoCntrService.deleteBlnoCntrByBlnoId(blnoId);
    }

    public Long commitEdiData(BlnoInfoVO blnoInfoVO, String userId){
        BlnoBaseInfoVO blnoBasInfoVO = blnoInfoVO.getBlnoBasInfoVO();
        //edi 的提单号 赋值 给  订舱号
        blnoBasInfoVO.setBookingNo(blnoBasInfoVO.getBookingNo());
        Long orUpdateSi = blnoService.createOrUpdateSi(blnoInfoVO, false, userId);
        LambdaUpdateWrapper<BlnoDO> lambdaUpdate = new LambdaUpdateWrapper<>();
        lambdaUpdate.eq(BlnoDO::getId, blnoBasInfoVO.getId() == null ? orUpdateSi : blnoBasInfoVO.getId())
                .set(BlnoDO::getSiStatus, SiStatusEnum.BookingProcessing.getValue())
                .set(BlnoDO::getSignOrderTime, LocalDateTime.now());
        blnoMapper.update(null, lambdaUpdate);
        blnoBasInfoVO.setId(orUpdateSi);
        saveOperateLog(blnoBasInfoVO, SI_OPERATE_TYPE, SUBMIT_SI.getValue(), SUBMIT_SI.getLabel());
        return orUpdateSi;
    }

    public Long saveOperateLog(BlnoBaseInfoVO baseInfoVO, String operateType, String operateTypeSub,
                                String operateDesc) {
        OperateLogCreateReqVO operateLog = new OperateLogCreateReqVO();
        operateLog.setBusinessId(baseInfoVO.getId());
        operateLog.setBusinessNo(baseInfoVO.getBookingNo());
        operateLog.setBusinessType(BusinessTypeEnum.SI.getValue());
        operateLog.setOperateType(operateType);
        operateLog.setOperateTypeSub(operateTypeSub);
        operateLog.setOperateDesc(operateDesc);
        return operateLogService.createOperateLog(operateLog);
    }

    public boolean checkLockVoyage(List<BlnoVslvoyDO> vslvoyList) {
        BlnoVslvoyDO vslvoy = VslvoyUtil.getFirstVslvoy(vslvoyList);
        if (vslvoy == null) {
            return false;
        }
        VoyageLockDO voyageLock = voyageLockService.findVoyageLock(vslvoy.getVesselCode(), vslvoy.getVoyageEx(),
                vslvoy.getPolCode(), ExImTypeEnum.EX.getValue());
        if (voyageLock == null) {
            return false;
        }
        return voyageLock.getVoyageLockFlag();
    }
}
